/*|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
  |                   Métodos Numéricos II                   |
  |           Autovalores e Autovetores - Tarefa 5           |
  |  Método da Potência Regular, Inversa e com Deslocamento  |
  |__________________________________________________________|*/

// É Linux ou é Windows?
#ifdef linux      // Sistema Operacional: Linux.
    #define sistema_operacional 0
#else
    #ifdef _WIN32 // Sistema Operacional: Windows.
        #define sistema_operacional 1
    #endif
#endif
// Vixe! Não é nenhum dos 2...
#ifndef sistema_operacional
    #error Sistema Operacional desconhecido!!! So rodo no Linux ou no Windows!!!
#endif

/*** LIXUX - INCLUDES E DEFINES ***/
#if (sistema_operacional == 0)
    #include "Extras/fuba_linux.h"
#endif

/*** WINDOWS - INCLUDES E DEFINES ***/
#if (sistema_operacional == 1)
    #include "Extras/fuba_win.h"
#endif

/*** DEFINES do programa ***/
// NADA!

/*** INCLUDES do programa ***/
#include <iostream>

// Classes:
#include "Classes/matriz.h"
#include "Classes/lu.h"
#include "Classes/potencia.h"
using namespace std;

int main(void) // PRINCIPAL //
{
    // Variáveis do MAIN:
    char escolha = '\0';
    int matriz_ordem;
    double matriz_valor, erro=0.0001, mi=0;
    matriz M, V;
    potencia POT;

//************************************
// Matriz dada na questão:
M.alocar(3,3);
M.set_aij(0,0,4);
M.set_aij(0,1,2);
M.set_aij(0,2,1);
M.set_aij(1,0,2);
M.set_aij(1,1,3);
M.set_aij(1,2,2);
M.set_aij(2,0,1);
M.set_aij(2,1,2);
M.set_aij(2,2,5);

// Chute inicial para o vetor "V":
V.alocar(3,1);
V.set_aij(0,0,1);
V.set_aij(1,0,1);
V.set_aij(2,0,1);
/***********************************/

    do{// MENU PRINCIPAL //
        limpar_tela();
        cout <<"#=============================================================#"<<endl;
        cout <<"#            Autovalores e Autovetores - Tarefa 5             #"<<endl;
        cout <<"#   Metodo da Potencia Regular, Inversa e com Deslocamento    #"<<endl;
        cout <<"#=============================================================#"<<endl;
        cout <<"> Escolha:"<<endl;
        cout <<"  (1) Inserir a dimensao da matriz;"<<endl;
        cout <<"  (2) Inserir a matriz;"<<endl;
        cout <<"  (3) Inserir o vetor de chute inicial;"<<endl;
        cout <<"  (4) Imprimir a matriz/vetor de chute;"<<endl;
        cout <<"  (5) Inserir o erro;"<<endl;
        cout <<"\n  -----------------------------------------------------------"<<endl;
        cout <<"  * Erro: "<<erro<<" *"<<endl;
        cout <<"  (R) Metodo da Potencia Regular (maior autovalor);"<<endl;
        cout <<"  (I) Metodo da Potencia Inversa (menor autovalor);"<<endl;
        cout <<"  (D) Metodo da Potencia Deslocada (qualquer autovalor);"<<endl;
        cout <<"  -----------------------------------------------------------\n"<<endl;
        cout <<"  (X) Sair do programa."<<endl;
        escolha = ler_tecla();
        switch(escolha)
        {
            case '1': /// Dimensão da matriz ///
            {
                limpar_tela();
                cout <<"+----------------------+"<<endl;
                cout <<"|  Dimensao da matriz  |"<<endl;
                cout <<"+----------------------+"<<endl;
                M.desalocar();
                V.desalocar();
                cout <<"* Digite a ordem da matriz: ";
                cin >> matriz_ordem;
                M.alocar(matriz_ordem,matriz_ordem);
                V.alocar(matriz_ordem,1);
                break;
            }

            case '2': /// Inserir os elementos da matriz ///
            {
                limpar_tela();
                cout <<"+----------------------------------+"<<endl;
                cout <<"|  Inserir os elementos da matriz  |"<<endl;
                cout <<"+----------------------------------+"<<endl;
                cout <<"> Matriz \"M\": "<<M.get_linhas()<<" x "<<M.get_colunas()<<" -> "<<(M.get_linhas() * M.get_colunas())<<" elementos."<<endl;
                for(int i=0 ; i<(M.get_linhas()) ; i++)
                {
                    for(int j=0 ; j<(M.get_colunas()) ; j++)
                    {
                        cout <<"* Digite o elemento M["<<i<<","<<j<<"]: ";
                        cin >> matriz_valor;
                        M.set_aij(i,j,matriz_valor);
                    }
                }
                break;
            }

            case '3': /// Inserir o vetor de chute inicial ///
            {
                limpar_tela();
                cout <<"+------------------------------------+"<<endl;
                cout <<"|  Inserir o vetor de chute inicial  |"<<endl;
                cout <<"+------------------------------------+"<<endl;
                cout <<"> Vetor \"V\": "<<V.get_linhas()<<" elementos."<<endl;
                for(int i=0 ; i<(V.get_linhas()) ; i++)
                {
                    cout <<"* Digite o elemento V["<<i<<"]: ";
                    cin >> matriz_valor;
                    V.set_aij(i,0,matriz_valor);
                }
                break;
            }

            case '4': /// Imprimir a matriz/vetor de chute ///
            {
                limpar_tela();
                cout <<"+------------------------------------+"<<endl;
                cout <<"|  Imprimir a matriz/vetor de chute  |"<<endl;
                cout <<"+------------------------------------+"<<endl;
                cout <<"* Matriz \"M\":"<<endl;
                M.imprimir();
                cout <<"\n* Vetor \"V\":"<<endl;
                V.imprimir();
                pausar();
                break;
            }

            case '5': /// Inserir o erro ///
            {
                limpar_tela();
                cout <<"+------------------+"<<endl;
                cout <<"|  Inserir o erro  |"<<endl;
                cout <<"+------------------+"<<endl;
                cout <<"* Digite o valor do erro: ";
                cin >> erro;
                break;
            }

            case 'R': /// Método da Potência Regular ///
            {
                limpar_tela();
                cout <<"+------------------------------+"<<endl;
                cout <<"|  Metodo da Potencia Regular  |"<<endl;
                cout <<"+------------------------------+"<<endl;
                if (POT.calcular_potencia_regular(&M,&V,erro))
                {
                    cout <<"* Maior autovalor da Matriz \"M\":"<<endl;
                    cout <<POT.get_autovalor()<<endl;
                    cout <<"\n* Autovetor correspondente: " <<endl;
                    (POT.get_autovetor())->imprimir();
                    cout<<endl;
                    POT.checar_autovalor_autovetor(&M);
                    cout<<endl;
                }
                pausar();
                break;
            }

            case 'I': /// Método da Potência Inversa ///
            {
                limpar_tela();
                cout <<"+------------------------------+"<<endl;
                cout <<"|  Metodo da Potencia Inversa  |"<<endl;
                cout <<"+------------------------------+"<<endl;
                if (POT.calcular_potencia_inversa(&M,&V,erro))
                {
                    cout <<"* Menor autovalor da Matriz \"M\":"<<endl;
                    cout <<POT.get_autovalor()<<endl;
                    cout <<"\n* Autovetor correspondente: " <<endl;
                    (POT.get_autovetor())->imprimir();
                    cout<<endl;
                    POT.checar_autovalor_autovetor(&M);
                    cout<<endl;
                }
                pausar();
                break;
            }

            case 'D': /// Método da Potência Deslocada ///
            {
                do{
                    limpar_tela();
                    cout <<"+--------------------------------+"<<endl;
                    cout <<"|  Metodo da Potencia Deslocada  |"<<endl;
                    cout <<"+--------------------------------+"<<endl;
                    cout <<"* Digite o valor do \"mi\""<<endl;
                    cout <<"  (ou ZERO para retornar ao menu anterior): ";
                    cin >> mi;
                    if (POT.calcular_potencia_deslocada(&M,&V,erro,mi))
                    {
                        cout <<"\n* Autovalor da Matriz \"M\":"<<endl;
                        cout <<POT.get_autovalor()<<endl;
                        cout <<"\n* Autovetor correspondente: " <<endl;
                        (POT.get_autovetor())->imprimir();
                        cout<<endl;
                        POT.checar_autovalor_autovetor(&M);
                        cout<<endl;
                    }
                    pausar();
                  }while(mi!=0);
                break;
            }
        }// fim do "switch(escolha)" //
      }while(escolha!='X');// fim do "MENU PRINCIPAL" //
    return(0);
}
